package com.alibaba.citrus.cr.platform.enhance.facade.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeSet;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import com.alibaba.acm.shaded.com.alibaba.metrics.StringUtils;
import com.alibaba.citrus.cr.common.annotation.FacadeInvoker;
import com.alibaba.citrus.cr.common.exception.FacadeException;
import com.alibaba.citrus.cr.common.util.PageUtils;
import com.alibaba.citrus.cr.platform.enhance.repository.CustomerAddressRelationRepository;
import com.alibaba.citrus.cr.platform.enhance.repository.CustomerAddressRepository;
import com.alibaba.citrus.cr.platform.enhance.repository.CustomerRepository;
import com.alibaba.cz.base.tool.StringUtil;
import com.alibaba.cz.base.tool.log.Log;
import com.alibaba.cz.base.tool.page.PageResult;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.lattice2.epoch.sdk.model.Result;

import com.epoch.app.bcorder.model.dto.*;
import com.epoch.app.bcorder.service.BaseDataService;
import com.epoch.app.bcorder.service.UnifiedInventoryService;
import com.epoch.app.crplatformenhance.api.customeraddressquery.dto.CustomerAddressQueryRequest;
import com.epoch.app.crplatformenhance.api.customeraddressquery.dto.QueryAddressPrincipalListRequest;
import com.epoch.app.crplatformenhance.api.customeraddressquery.dto.QueryCustomerAddresByIdRequest;
import com.epoch.app.crplatformenhance.api.customeraddressquery.service.CustomerAddressQueryService;
import com.epoch.app.crplatformenhance.channel.service.ChannelService;
import com.epoch.app.crplatformenhance.domain.customeraddress.dto.LoadCustomerAddresRequest;
import com.epoch.app.crplatformenhance.domain.customeraddress.dto.LoadCustomerAddressRequest;
import com.epoch.app.crplatformenhance.domain.customeraddress.model.CustomerAddress;
import com.epoch.app.crplatformenhance.domain.customeraddress.service.CustomerAddressService;
import com.epoch.app.crplatformenhance.domain.scitemgroup.dto.LoadScItemGroupListRequest;
import com.epoch.app.crplatformenhance.domain.scitemgroup.model.ScItemGroup;
import com.epoch.app.crplatformenhance.domain.scitemgroup.service.ScItemGroupService;
import com.epoch.app.crplatformenhance.dto.feature.FullOrganizationValue;
import com.epoch.app.crplatformenhance.dto.request.*;
import com.epoch.app.crplatformenhance.enums.OrganizationTypeEnum;
import com.epoch.app.crplatformenhance.model.dto.ChannelResponse;
import com.epoch.app.crplatformenhance.model.dto.CustomerAddressRelationLoadListRequest;
import com.epoch.app.crplatformenhance.model.dto.CustomerAddressRelationSDO;
import com.epoch.app.crplatformenhance.model.dto.QueryChannelRequest;
import com.epoch.app.crplatformenhance.model.dto.StringList;
import com.epoch.app.crplatformenhance.model.enums.CustomerRelationBizTypeEnum;
import com.epoch.app.crplatformenhance.sdo.CustomerAddressSDO;
import com.epoch.app.crplatformenhance.sdo.CustomerSDO;
import com.google.common.collect.Lists;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

@Primary
@Service
public class CustomerAddressQueryServiceImpl implements CustomerAddressQueryService {

    private static Log log = Log.getLogger(CustomerAddressQueryServiceImpl.class);

    @Resource
    CustomerAddressRepository addressRepository;

    @Resource
    CustomerAddressRelationRepository customerAddressRelationRepository;

    @Resource
    CustomerRepository customerRepository;

    @Resource
    private BaseDataService baseDataService;

    @Resource
    private CustomerAddressService customerAddressService;

    @Resource
    ChannelService channelService;

    @Resource
    ScItemGroupService scItemGroupService;

    @Resource
    private UnifiedInventoryService unifiedInventoryService;


    @Override
    @FacadeInvoker
    public Result<CustomerAddressSDO> queryCustomerAddress(CustomerAddressRequest customerAddressRequest) {
        CustomerAddressSDO response = addressRepository.query(customerAddressRequest);
        return Result.success(response);
    }

    @Override
    @FacadeInvoker
    public Result<List<CustomerAddressSDO>> batchQueryCustomerAddress(CustomerAddressBatchRequest addressBatchRequest) {
        List<CustomerAddressSDO> pageResult = addressRepository.batchQuery(addressBatchRequest);
        return Result.success(pageResult);
    }

    @Override
    @FacadeInvoker
    public Result<List<CustomerAddressSDO>> pageQueryCustomerAddress(QueryAddressRequest queryAddressRequest) {
        PageResult<List<CustomerAddressSDO>> pageResult = addressRepository.pageQuery(queryAddressRequest);
        return Result.listSuccess(pageResult.getContent(), pageResult.getTotal());
    }

    @Override
    @FacadeInvoker
    public Result<List<CustomerAddressSDO>> queryPrincipalList() {
        QueryAddressRequest queryAddressRequest = new QueryAddressRequest();
        PageResult<List<CustomerAddressSDO>> listPageResult = addressRepository.pageQuery(queryAddressRequest);
        List<CustomerAddressSDO> pageResultContent = listPageResult.getContent();
        List<CustomerAddressSDO> addressSDOS = pageResultContent.stream()
                .collect(Collectors.collectingAndThen(Collectors.toCollection(()
                        -> new TreeSet<>(Comparator.comparing(CustomerAddressSDO::getPrincipal))), ArrayList::new));
        int total = listPageResult.getTotal() - (pageResultContent.size() - addressSDOS.size());
        PageResult<List<CustomerAddressSDO>> pageResult = PageResult.of(addressSDOS, total);
        return Result.listSuccess(pageResult.getContent(), pageResult.getTotal());
    }

//    @Override
    @FacadeInvoker
    public Result<StringList> queryAddressPrincipalList(QueryAddressPrincipalListRequest queryAddressPrincipalListRequest) {
        if (queryAddressPrincipalListRequest.getBizType() == null && StringUtil.isBlank(queryAddressPrincipalListRequest.getBizId())) {
            throw new FacadeException("OTS-01-004-02-15-001");
        }
        OrganizationTypeEnum byOrganizationType =
                Arrays.stream(OrganizationTypeEnum.values()).filter(source -> Objects.equals(queryAddressPrincipalListRequest.getBizType(), source.getCode())).findFirst().orElse(null);
        if (byOrganizationType == null) {
            throw new FacadeException("OTS-01-004-02-15-001");
        }
        FullOrganizationValue fullOrganizationValue = new FullOrganizationValue();
        fullOrganizationValue.setLimit(queryAddressPrincipalListRequest.getLimit());
        fullOrganizationValue.setStart(queryAddressPrincipalListRequest.getStart());
        switch (byOrganizationType) {
            case SALES_DEPARTMENT:
                fullOrganizationValue.setOrgSalesDepartmentCode(queryAddressPrincipalListRequest.getBizId());
                break;
            case SALES_CHANNEL:
                fullOrganizationValue.setOrgSalesChannelCode(queryAddressPrincipalListRequest.getBizId());
                break;
            case SALES_ORGANIZATION:
                fullOrganizationValue.setOrgSalesOrganizationCode(queryAddressPrincipalListRequest.getBizId());
                break;
            case COMPANY:
                fullOrganizationValue.setOrgBusinessUnitCode(queryAddressPrincipalListRequest.getBizId());
                break;
            default:
        }

        //搜索条件不为空  则全量返回结果
        if (StringUtils.isNotBlank(queryAddressPrincipalListRequest.getEmployeeName())) {
            if (queryAddressPrincipalListRequest.getEmployeeName().length()>50) {
                throw new FacadeException("OTS-01-004-02-15-010");
            }

            List<String> principalIds = new ArrayList<>();
            int pageSize = 800;
            fullOrganizationValue.setStart(0);
            fullOrganizationValue.setLimit(pageSize);

            BaselineGetEmployeesEs2Request getEmployeesRequest = new BaselineGetEmployeesEs2Request();
            getEmployeesRequest.setName(queryAddressPrincipalListRequest.getEmployeeName());
            getEmployeesRequest.setType(1);
            getEmployeesRequest.setStatus(1);
            getEmployeesRequest.setStart(0);
            getEmployeesRequest.setLimit(pageSize);
            Result<List<EmployeeSDO>> employeeResult = baseDataService.baselineGetEmployeesEs2(getEmployeesRequest);
            if (employeeResult==null || employeeResult.getTotal()==0 || CollectionUtils.isEmpty(employeeResult.getResult())) {
                return Result.success(new StringList(principalIds));
            }
            List<String> employeeIds = employeeResult.getResult().stream().map(x->x.getId()).collect(Collectors.toList());
            Result<StringList> addressResult = pageQueryAddressPrincipalList(fullOrganizationValue, employeeIds);
            if (addressResult!=null && addressResult.getResult()!=null && !CollectionUtils.isEmpty(addressResult.getResult().getList())) {
                principalIds.addAll(addressResult.getResult().getList());
            }

            if (employeeResult.getTotal()>pageSize) {
                int page = PageUtils.getTotalPage(employeeResult.getTotal(), pageSize);
                for (int i = 1; i < page; i++) {
                    getEmployeesRequest.setStart(i*pageSize);
                    getEmployeesRequest.setLimit(pageSize);
                    Result<List<EmployeeSDO>> employeeResult2 = baseDataService.baselineGetEmployeesEs2(getEmployeesRequest);
                    if (employeeResult2==null || CollectionUtils.isEmpty(employeeResult2.getResult())) {
                        continue;
                    }

                    employeeIds = employeeResult2.getResult().stream().map(x->x.getId()).collect(Collectors.toList());
                    Result<StringList> addressResult2 = pageQueryAddressPrincipalList(fullOrganizationValue, employeeIds);
                    if (addressResult2!=null && addressResult2.getResult()!=null && !CollectionUtils.isEmpty(addressResult2.getResult().getList())) {
                        principalIds.addAll(addressResult2.getResult().getList());
                    }
                }
            }

            StringList stringList = StringList.builder().list(principalIds).build();
            Result ret = Result.success(stringList);
            ret.setTotal(principalIds.size());
            return ret;
        }

        return pageQueryAddressPrincipalList(fullOrganizationValue, null);
    }


    private Result<StringList> pageQueryAddressPrincipalList(FullOrganizationValue fullOrganizationValue, List<String> employeeIdList){
        Integer addressCount = addressRepository.queryAddressPrincipalCount(fullOrganizationValue,employeeIdList);
        if (addressCount == null || addressCount <= 0) {
            return Result.success(new StringList(new ArrayList<>()));
        }
        List<String> strings = addressRepository.queryAddressPrincipalList(fullOrganizationValue,employeeIdList);
        StringList stringList = StringList.builder().list(strings).build();
        Result ret = Result.success(stringList);
        ret.setTotal(addressCount);
        return ret;
    }

    @Override
    public Object customerAddressQuery(CustomerAddressQueryRequest customerAddressQueryRequest) {
        String id = customerAddressQueryRequest.getId();
        if (StringUtils.isBlank(id)) {
            throw new FacadeException("OTS-01-004-02-16-009");
        }
        LoadCustomerAddresRequest request = new LoadCustomerAddresRequest();
        request.setId(id);
        CustomerAddress customerAddress = customerAddressService.loadCustomerAddres(request);
        if (null == customerAddress) {
            throw new FacadeException("OTS-01-004-02-16-018");
        }

        CustomerAddressSDO customerAddressSDO = new CustomerAddressSDO();
        BeanUtils.copyProperties(customerAddress,customerAddressSDO);
        customerAddressSDO.setId(String.valueOf(customerAddress.getId()));

        // 查询送达方客户负责人
        CustomerAddressRelationLoadListRequest relationLoadListRequest = new CustomerAddressRelationLoadListRequest();
        relationLoadListRequest.setAddressId(String.valueOf(customerAddress.getId()));
        relationLoadListRequest.setAddressCode(customerAddress.getAddressCode());
        relationLoadListRequest.setBizType(CustomerRelationBizTypeEnum.ADDRESS_CUSTOMER_PRINCIPAL_RELATION.getValue());
        List<CustomerAddressRelationSDO> list = customerAddressRelationRepository.queryRelationList(relationLoadListRequest);
        if(org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)){
            customerAddressSDO.setCustomerPrincipalList(list.stream().map(x->x.getRelationId()).collect(Collectors.toList()));
        }

        // 销售组织
        String orgSaleOrganizationCode = customerAddress.getOrgSaleOrganizationCode();
        // 获取销售组织下的销售渠道列表
        List<String> channelCodeList = getList(orgSaleOrganizationCode);
        String orgSaleChannelCode = customerAddress.getOrgSaleChannelCode();
        if (CollectionUtils.isEmpty(channelCodeList) || !channelCodeList.contains(orgSaleChannelCode)) {
            customerAddressSDO.setOrgSaleChannelCode("");
            customerAddressSDO.setOrgSaleDepartmentCode("");
            customerAddressSDO.setPrincipal("");
            return customerAddressSDO;
        }
        // 获取销售组织下的销售渠道列表
        List<String> departmentCodeList = getList(orgSaleChannelCode);
        String orgSaleDepartmentCode = customerAddress.getOrgSaleDepartmentCode();
        if (CollectionUtils.isEmpty(departmentCodeList) || !departmentCodeList.contains(orgSaleDepartmentCode)) {
            customerAddressSDO.setOrgSaleDepartmentCode("");
            customerAddressSDO.setPrincipal("");
            return customerAddressSDO;
        }
        // 获取部门下的负责人
        GetEmployeeSelectRequest getEmployeeSelectRequest = new GetEmployeeSelectRequest();
        getEmployeeSelectRequest.setId(orgSaleDepartmentCode);
        GetEmployeeSelectResponse employeeSelect = baseDataService.getEmployeeSelect(getEmployeeSelectRequest);
        if (null == employeeSelect) {
            throw new FacadeException("OTS-01-004-02-16-017");
        }
        List employeeResult = employeeSelect.getResult();
        if (CollectionUtils.isEmpty(employeeResult)) {
            customerAddressSDO.setPrincipal("");
            return customerAddressSDO;
        }
        List<Map> employeeList = JSONObject.parseArray(JSON.toJSONString(employeeResult), Map.class);
        List<String> employeeCodeList = employeeList.stream().map(map -> map.get("value").toString()).collect(Collectors.toList());
        String principal = customerAddress.getPrincipal();
        if (!employeeCodeList.contains(principal)) {
            customerAddressSDO.setPrincipal("");
            return customerAddressSDO;
        }
        return customerAddressSDO;
    }

    @NotNull
    private List<String> getList(String parentId) {
        GetOrganizationSelectsRequest getOrganizationSelectsRequest = new GetOrganizationSelectsRequest();
        getOrganizationSelectsRequest.setParentId(parentId);
        GetOrganizationSelectsResponse organizationSelects = baseDataService.getOrganizationSelects(getOrganizationSelectsRequest);
        if (null == organizationSelects) {
            return Lists.newArrayList();
        }
        List result = organizationSelects.getResult();
        if (CollectionUtils.isEmpty(result)) {
            return Lists.newArrayList();
        }
        List<Map> list = JSONObject.parseArray(JSON.toJSONString(result), Map.class);
        List<String> codeList = list.stream().map(map -> map.get("value").toString()).collect(Collectors.toList());
        return codeList;
    }

    @Override
    public Result<CustomerAddressSDO> queryCustomerAddresById(QueryCustomerAddresByIdRequest queryCustomerAddresByIdRequest) {
        CustomerAddressSDO addressSDO = addressRepository.load(queryCustomerAddresByIdRequest.getId());
        if(Objects.nonNull(addressSDO)){
            setAddressDetailInfo(addressSDO);
        }
        return Result.success(addressSDO);
    }

    private CustomerAddressSDO setAddressDetailInfo(CustomerAddressSDO customerAddressSDO) {
        String channelName = "";
        String itemGroupName = "";
        String shippingConditions = "";
        String frozenStatus = "";
        String kunn2 = "";
        String storeHouse = "";
        String parvw = "";
        String transportAreaName = "";
        String regio = "";
        String customerGroup = "";
        String outOrgSalesDepartmentName = "";
        String storeHouseName = "";
        if (!org.springframework.util.StringUtils.isEmpty(customerAddressSDO.getFeatures())) {
            JSONObject jsonobject = JSONObject.parseObject(customerAddressSDO.getFeatures());
            channelName = jsonobject.getString("channelName");
            itemGroupName = jsonobject.getString("itemGroupName");
            shippingConditions = jsonobject.getString("shippingConditions");
            frozenStatus = jsonobject.getString("frozenStatus");
            kunn2 = jsonobject.getString("kunn2");
            storeHouse = jsonobject.getString("storeHouse");
            parvw = jsonobject.getString("parvw");
            transportAreaName = jsonobject.getString("transportAreaName");
            regio = jsonobject.getString("regio");
            customerGroup = jsonobject.getString("customerGroup");
            outOrgSalesDepartmentName = jsonobject.getString("outOrgSalesDepartmentName");
            storeHouseName = jsonobject.getString("storeHouseName");
        }

        customerAddressSDO.setChannelName(channelName);
        customerAddressSDO.setItemGroupName(itemGroupName);
        customerAddressSDO.setTransportAreaName(transportAreaName);
        if (Objects.isNull(customerAddressSDO.getStatus())) {
            frozenStatus = "禁用";
        } else {
            frozenStatus = customerAddressSDO.getStatus() == 1 ? "启用" : "禁用";
        }
        customerAddressSDO.setFrozenStatus(frozenStatus);
        customerAddressSDO.setShippingConditions(shippingConditions);
        customerAddressSDO.setKunn2(kunn2);
        customerAddressSDO.setStoreHouse(storeHouse);
        customerAddressSDO.setParvw(parvw);
        customerAddressSDO.setRegio(regio);
        customerAddressSDO.setCustomerGroup(customerGroup);
        customerAddressSDO.setOutOrgSalesDepartmentName(outOrgSalesDepartmentName);
        //取渠道名称
        QueryChannelRequest queryChannelRequest = new QueryChannelRequest();
        queryChannelRequest.setChannelCode(customerAddressSDO.getChannelCode());
        Result<ChannelResponse> channelDetail = channelService.queryChannelDetail(queryChannelRequest);
        if (Objects.nonNull(channelDetail) && Objects.nonNull(channelDetail.getResult())) {
            ChannelResponse detailResult = channelDetail.getResult();
            customerAddressSDO.setChannelName(detailResult.getChannelName());
        }
        //取货品组名称
        LoadScItemGroupListRequest listRequest = new LoadScItemGroupListRequest();
        listRequest.setOutCode(customerAddressSDO.getItemGroup());
        Result<List<ScItemGroup>> listResult = scItemGroupService.loadScItemGroupList(listRequest);
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(listResult.getResult())) {
            ScItemGroup group = listResult.getResult().stream().findFirst().get();
            customerAddressSDO.setItemGroupName(group.getName());
        }
        // 取客户名称
        if (StringUtils.isNotBlank(customerAddressSDO.getCustomerCode())) {
            CustomerRequest customerRequest = new CustomerRequest();
            customerRequest.setCode(customerAddressSDO.getCustomerCode());
            CustomerSDO customerSDO = customerRepository.query(customerRequest);
            if (Objects.nonNull(customerSDO)) {
                customerAddressSDO.setCustomerName(customerSDO.getName());
            }
        }
        //取仓库名称
        if (org.apache.commons.lang3.StringUtils.isNotBlank(storeHouseName)) {
            customerAddressSDO.setStoreHouseName(storeHouseName);
        } else {
            WmsQueryWarehouseZoneListRequest warehouseZoneListRequest = WmsQueryWarehouseZoneListRequest.builder().code(storeHouse).build();
            WmsQueryWarehouseZoneListResponse zoneListResponse = unifiedInventoryService.wmsQueryWarehouseZoneList(warehouseZoneListRequest);
            if (Objects.nonNull(zoneListResponse) && org.apache.commons.collections4.CollectionUtils.isNotEmpty(zoneListResponse.getResult())) {
                WarehouseInfo warehouseInfo = zoneListResponse.getResult().stream().findFirst().get();
                customerAddressSDO.setStoreHouseName(warehouseInfo.getName());
            }

        }
        return customerAddressSDO;
    }

    /**
     * 根据送达方地址，查询客户id
     * @param customerAddressRequest 客户地址请求
     * @return 客户地址
     */
    @FacadeInvoker
    @Override
    public Result<CustomerAddressSDO> queryCustomerAddressByShipAddressId(CustomerAddressRequest customerAddressRequest) {
        LoadCustomerAddressRequest loadRequest = new LoadCustomerAddressRequest();
        BeanUtils.copyProperties(customerAddressRequest, loadRequest);
        CustomerAddress customerAddress = customerAddressService.loadCustomerAddress(loadRequest);
        CustomerAddressSDO customerAddressSDO = new CustomerAddressSDO();
        if (customerAddressSDO != null) {
            BeanUtils.copyProperties(customerAddress, customerAddressSDO);
        }
        return Result.success(customerAddressSDO);
    }

}
